From 7263379ba795cb86462825f3b13a2a92c22f05eb Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 20 Feb 2007 11:57:06 +0000 Subject: [PATCH] xen/x86: Better BUG back traces. Signed-off-by: Keir Fraser --- xen/arch/x86/mm/shadow/common.c | 87 ++++++++++++++++---------------- xen/arch/x86/mm/shadow/multi.c | 7 ++- xen/arch/x86/traps.c | 23 ++++++--- xen/include/asm-ia64/bug.h | 6 +++ xen/include/asm-powerpc/bug.h | 6 +++ xen/include/asm-x86/bug.h | 13 +++++ xen/include/asm-x86/processor.h | 5 -- xen/include/asm-x86/x86_32/bug.h | 19 +++++++ xen/include/asm-x86/x86_64/bug.h | 19 +++++++ xen/include/xen/lib.h | 5 +- 10 files changed, 129 insertions(+), 61 deletions(-) create mode 100644 xen/include/asm-ia64/bug.h create mode 100644 xen/include/asm-powerpc/bug.h create mode 100644 xen/include/asm-x86/bug.h create mode 100644 xen/include/asm-x86/x86_32/bug.h create mode 100644 xen/include/asm-x86/x86_64/bug.h diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 0751db77a9..23d3351605 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -929,49 +929,7 @@ mfn_t shadow_alloc(struct domain *d, /* Find smallest order which can satisfy the request. */ for ( i = order; i <= SHADOW_MAX_ORDER; i++ ) if ( !list_empty(&d->arch.paging.shadow.freelists[i]) ) - { - sp = list_entry(d->arch.paging.shadow.freelists[i].next, - struct shadow_page_info, list); - list_del(&sp->list); - - /* We may have to halve the chunk a number of times. */ - while ( i != order ) - { - i--; - sp->order = i; - list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]); - sp += 1 << i; - } - d->arch.paging.shadow.free_pages -= 1 << order; - - /* Init page info fields and clear the pages */ - for ( i = 0; i < 1<domain_dirty_cpumask; - tlbflush_filter(mask, sp[i].tlbflush_timestamp); - if ( unlikely(!cpus_empty(mask)) ) - { - perfc_incrc(shadow_alloc_tlbflush); - flush_tlb_mask(mask); - } - /* Now safe to clear the page for reuse */ - p = sh_map_domain_page(shadow_page_to_mfn(sp+i)); - ASSERT(p != NULL); - clear_page(p); - sh_unmap_domain_page(p); - INIT_LIST_HEAD(&sp[i].list); - sp[i].type = shadow_type; - sp[i].pinned = 0; - sp[i].logdirty = 0; - sp[i].count = 0; - sp[i].backpointer = backpointer; - sp[i].next_shadow = NULL; - perfc_incr(shadow_alloc_count); - } - return shadow_page_to_mfn(sp); - } + goto found; /* If we get here, we failed to allocate. This should never happen. * It means that we didn't call shadow_prealloc() correctly before @@ -979,6 +937,49 @@ mfn_t shadow_alloc(struct domain *d, * we might free up higher-level pages that the caller is working on. */ SHADOW_PRINTK("Can't allocate %i shadow pages!\n", 1 << order); BUG(); + + found: + sp = list_entry(d->arch.paging.shadow.freelists[i].next, + struct shadow_page_info, list); + list_del(&sp->list); + + /* We may have to halve the chunk a number of times. */ + while ( i != order ) + { + i--; + sp->order = i; + list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]); + sp += 1 << i; + } + d->arch.paging.shadow.free_pages -= 1 << order; + + /* Init page info fields and clear the pages */ + for ( i = 0; i < 1<domain_dirty_cpumask; + tlbflush_filter(mask, sp[i].tlbflush_timestamp); + if ( unlikely(!cpus_empty(mask)) ) + { + perfc_incrc(shadow_alloc_tlbflush); + flush_tlb_mask(mask); + } + /* Now safe to clear the page for reuse */ + p = sh_map_domain_page(shadow_page_to_mfn(sp+i)); + ASSERT(p != NULL); + clear_page(p); + sh_unmap_domain_page(p); + INIT_LIST_HEAD(&sp[i].list); + sp[i].type = shadow_type; + sp[i].pinned = 0; + sp[i].logdirty = 0; + sp[i].count = 0; + sp[i].backpointer = backpointer; + sp[i].next_shadow = NULL; + perfc_incr(shadow_alloc_count); + } + return shadow_page_to_mfn(sp); } diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index a3d8180d93..7af102f89b 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3196,11 +3196,10 @@ sh_update_linear_entries(struct vcpu *v) int unmap_l2e = 0; #if GUEST_PAGING_LEVELS == 2 + /* Shadow l3 tables were built by sh_update_cr3 */ - if ( shadow_mode_external(d) ) - shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; - else - BUG(); /* PV 2-on-3 is not supported yet */ + BUG_ON(!shadow_mode_external(d)); /* PV 2-on-3 is unsupported */ + shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; #else /* GUEST_PAGING_LEVELS == 3 */ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 19d3b972e7..3eff302b7e 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -624,14 +624,23 @@ asmlinkage int do_invalid_op(struct cpu_user_regs *regs) if ( unlikely(!guest_mode(regs)) ) { - char sig[5]; - /* Signature (ud2; .ascii "dbg") indicates dump state and continue. */ - if ( (__copy_from_user(sig, (char *)regs->eip, sizeof(sig)) == 0) && - (memcmp(sig, "\xf\xb""dbg", sizeof(sig)) == 0) ) + struct bug_frame bug; + if ( (__copy_from_user(&bug, (char *)regs->eip, sizeof(bug)) == 0) && + (memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) == 0) && + (memcmp(bug.mov, BUG_MOV_STR, sizeof(bug.mov)) == 0) && + (bug.ret == 0xc2) ) { - show_execution_state(regs); - regs->eip += sizeof(sig); - return EXCRET_fault_fixed; + char *filename = (char *)bug.filename; + unsigned int line = bug.line & 0x7fff; + int is_bug = !(bug.line & 0x8000); + printk("Xen %s at %.50s:%d\n", + is_bug ? "BUG" : "State Dump", filename, line); + if ( !is_bug ) + { + show_execution_state(regs); + regs->eip += sizeof(bug); + return EXCRET_fault_fixed; + } } DEBUGGER_trap_fatal(TRAP_invalid_op, regs); show_execution_state(regs); diff --git a/xen/include/asm-ia64/bug.h b/xen/include/asm-ia64/bug.h new file mode 100644 index 0000000000..2caf275c39 --- /dev/null +++ b/xen/include/asm-ia64/bug.h @@ -0,0 +1,6 @@ +#ifndef __IA64_BUG_H__ +#define __IA64_BUG_H__ + +#define BUG() __bug(__FILE__, __LINE__) + +#endif /* __IA64_BUG_H__ */ diff --git a/xen/include/asm-powerpc/bug.h b/xen/include/asm-powerpc/bug.h new file mode 100644 index 0000000000..20d7d4bfb9 --- /dev/null +++ b/xen/include/asm-powerpc/bug.h @@ -0,0 +1,6 @@ +#ifndef __POWERPC_BUG_H__ +#define __POWERPC_BUG_H__ + +#define BUG() __bug(__FILE__, __LINE__) + +#endif /* __POWERPC_BUG_H__ */ diff --git a/xen/include/asm-x86/bug.h b/xen/include/asm-x86/bug.h new file mode 100644 index 0000000000..a85f4810b8 --- /dev/null +++ b/xen/include/asm-x86/bug.h @@ -0,0 +1,13 @@ +#ifndef __X86_BUG_H__ +#define __X86_BUG_H__ + +#ifdef __x86_64__ +#include +#else +#include +#endif + +#define BUG() __BUG(__FILE__, __LINE__) +#define dump_execution_state() __BUG(__FILE__, __LINE__ | 0x8000) + +#endif /* __X86_BUG_H__ */ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 0d1d2533ce..321219c853 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -565,11 +565,6 @@ void compat_show_guest_stack(struct cpu_user_regs *, int lines); #define compat_show_guest_stack(regs, lines) ((void)0) #endif -/* Dumps current register and stack state. */ -#define dump_execution_state() \ - /* NB. Needs interrupts enabled else we end up in fatal_trap(). */ \ - __asm__ __volatile__ ( "pushf ; sti ; ud2 ; .ascii \"dbg\" ; popf" ) - extern void mtrr_ap_init(void); extern void mtrr_bp_init(void); diff --git a/xen/include/asm-x86/x86_32/bug.h b/xen/include/asm-x86/x86_32/bug.h new file mode 100644 index 0000000000..6ab3720c52 --- /dev/null +++ b/xen/include/asm-x86/x86_32/bug.h @@ -0,0 +1,19 @@ +#ifndef __X86_32_BUG_H__ +#define __X86_32_BUG_H__ + +struct bug_frame { + unsigned char ud2[2]; + unsigned char mov[1]; + unsigned long filename; + unsigned char ret; + unsigned short line; +} __attribute__((packed)); + +#define BUG_MOV_STR "\xbc" + +#define __BUG(file, line) \ + asm volatile ( \ + "ud2 ; .byte 0xbc ; .long %c1 ; ret $%c0" \ + : : "i" (line), "i" (file) ) + +#endif /* __X86_32_BUG_H__ */ diff --git a/xen/include/asm-x86/x86_64/bug.h b/xen/include/asm-x86/x86_64/bug.h new file mode 100644 index 0000000000..d5413db3d4 --- /dev/null +++ b/xen/include/asm-x86/x86_64/bug.h @@ -0,0 +1,19 @@ +#ifndef __X86_64_BUG_H__ +#define __X86_64_BUG_H__ + +struct bug_frame { + unsigned char ud2[2]; + unsigned char mov[2]; + unsigned long filename; + unsigned char ret; + unsigned short line; +} __attribute__((packed)); + +#define BUG_MOV_STR "\x48\xbc" + +#define __BUG(file, line) \ + asm volatile ( \ + "ud2 ; .byte 0x48,0xbc ; .quad %c1 ; ret $%c0" \ + : : "i" (line), "i" (file) ) + +#endif /* __X86_64_BUG_H__ */ diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 78c57faf06..ded2cfbb38 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -7,9 +7,10 @@ #include #include #include +#include + +void __bug(char *file, int line) __attribute__((noreturn)); -extern void __bug(char *file, int line) __attribute__((noreturn)); -#define BUG() __bug(__FILE__, __LINE__) #define BUG_ON(_p) do { if (_p) BUG(); } while ( 0 ) /* Force a compilation error if condition is true */ -- 2.30.2